﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.UI.WebControls;
using System.Linq.Expressions;
using Mulala.Cavan.Domain.MainBoundedContext.DictionaryModule;
using Spring.Context;
using Spring.Context.Support;
using Mulala.Cavan.Application.MainBoundedContext.MulalaModule;
using Mulala.Cavan.Domain.MainBoundedContext.SearchModule;

namespace Mulala.Cavan.Presentation.Seedwork
{
    public static class Ext
    {
        public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, string name, DictionaryIdentifier.GroupType type, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
        {
            IApplicationContext context = ContextRegistry.GetContext();
            ITagAppService tagAppService = context.GetObject(MulalaAppServiceConst.TAGAPPSERVICE) as ITagAppService;
            TagSearch tagSearch = TagSearchFactory.CreateTagSearch(type);
            var tags = tagAppService.GetBySearch(tagSearch).ToList();

            return ListControlUtil.GenerateHtml(name, tags, repeatDirection, "radio", null);
        }

        public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, DictionaryIdentifier.GroupType type, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
        {
            IApplicationContext context = ContextRegistry.GetContext();
            ITagAppService tagAppService = context.GetObject(MulalaAppServiceConst.TAGAPPSERVICE) as ITagAppService;
            TagSearch tagSearch = TagSearchFactory.CreateTagSearch(type);
            var tags = tagAppService.GetBySearch(tagSearch).ToList();

            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);

            string name = ExpressionHelper.GetExpressionText(expression);

            string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

            return ListControlUtil.GenerateHtml(fullHtmlFieldName, tags, repeatDirection, "radio", metadata.Model);
        }



        public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, DictionaryIdentifier.GroupType type, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
        {
            IApplicationContext context = ContextRegistry.GetContext();
            ITagAppService tagAppService = context.GetObject(MulalaAppServiceConst.TAGAPPSERVICE) as ITagAppService;
            TagSearch tagSearch = TagSearchFactory.CreateTagSearch(type);
            var tags = tagAppService.GetBySearch(tagSearch).ToList();

            return ListControlUtil.GenerateHtml(name, tags, repeatDirection, "checkbox", null);
        }

        public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, DictionaryIdentifier.GroupType type, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
        {
            IApplicationContext context = ContextRegistry.GetContext();
            ITagAppService tagAppService = context.GetObject(MulalaAppServiceConst.TAGAPPSERVICE) as ITagAppService;
            TagSearch tagSearch = TagSearchFactory.CreateTagSearch(type);
            var tags = tagAppService.GetBySearch(tagSearch).ToList();

            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);

            string name = ExpressionHelper.GetExpressionText(expression);

            string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

            return ListControlUtil.GenerateHtml(fullHtmlFieldName, tags, repeatDirection, "checkbox", metadata.Model);
        }

        public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, DictionaryIdentifier.GroupType type,object htmlAttributes)
        {
              IDictionary<string, object> dictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
              IApplicationContext context = ContextRegistry.GetContext();
              ITagAppService tagAppService = context.GetObject(MulalaAppServiceConst.TAGAPPSERVICE) as ITagAppService;
              TagSearch tagSearch = TagSearchFactory.CreateTagSearch(type);
              var tags = tagAppService.GetBySearch(tagSearch).ToList();
              ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);

              string name = ExpressionHelper.GetExpressionText(expression);

              string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

              if (null != dictionary && dictionary.ContainsKey("id"))
              {
                  object id = string.Empty;
                  dictionary.TryGetValue("id", out id);
                  return ListControlUtil.GenerateHtml(fullHtmlFieldName, id.ToString(), tags, metadata.Model);
              }
              return ListControlUtil.GenerateHtml(fullHtmlFieldName, fullHtmlFieldName, tags, metadata.Model);
        }
    }

    public static class ListControlUtil
    {
        public static MvcHtmlString GenerateHtml(string name, IList<Tag> tags, RepeatDirection repeatDirection, string type, object stateValue)
        {
            TagBuilder table = new TagBuilder("table");

            int i = 0;
            bool isCheckBox = type == "checkbox";

            if (repeatDirection == RepeatDirection.Horizontal)
            {
                TagBuilder tr = new TagBuilder("tr");

                foreach (var tag in tags)
                {
                    i++;
                    string id = string.Format("{0}_{1}", name, i);
                    TagBuilder td = new TagBuilder("td");
                    bool isChecked = false;

                    if (isCheckBox)
                    {

                        IEnumerable<string> currentValues = stateValue as IEnumerable<string>;

                        isChecked = (null != currentValues && currentValues.Contains(tag.Value));

                    }
                    else
                    {
                        string currentValue = stateValue as string;
                        isChecked = (null != currentValue && tag.Value == currentValue);
                    }

                    td.InnerHtml = GenerateRadioHtml(name, id, tag.Text, tag.Value, isChecked, type);
                    tr.InnerHtml += td.ToString();
                }
                table.InnerHtml = tr.ToString();
            }
            else
            {
                foreach (var tag in tags)
                {
                    TagBuilder tr = new TagBuilder("tr");
                    i++;
                    string id = string.Format("{0}_{1}", name, i);
                    TagBuilder td = new TagBuilder("td");
                    bool isChecked = false;

                    if (isCheckBox)
                    {
                        IEnumerable<string> currentValues = stateValue as IEnumerable<string>;
                        isChecked = (null != currentValues && currentValues.Contains(tag.Value));
                    }
                    else
                    {
                        string currentValue = stateValue as string;
                        isChecked = (null != currentValue && tag.Value == currentValue);
                    }

                    td.InnerHtml = GenerateRadioHtml(name, id, tag.Text, tag.Value, isChecked, type);
                    tr.InnerHtml = td.ToString();
                    table.InnerHtml += tr.ToString();
                }
            }
            return new MvcHtmlString(table.ToString());
        }

        public static MvcHtmlString GenerateHtml(string fullHtmlFieldName, string id, IList<Tag> tags, object stateValue)
        {
            TagBuilder select = new TagBuilder("select");
            select.GenerateId(id);
            select.MergeAttribute("name", fullHtmlFieldName, true);
            string currentValue = stateValue.ToString();
            foreach (var tag in tags)
            {
                select.InnerHtml = select.InnerHtml + GenerateOptionHtml(tag.Text, tag.Value, tag.Value == currentValue);
            }

            return new MvcHtmlString(select.ToString());
        }

        private static string GenerateRadioHtml(string name, string id, string labelText, string value, bool isChecked, string type)
        {
            StringBuilder sb = new StringBuilder();
            TagBuilder label = new TagBuilder("label");
            label.MergeAttribute("for", id);
            label.SetInnerText(labelText);
            TagBuilder input = new TagBuilder("input");

            input.GenerateId(id);
            input.MergeAttribute("name", name);
            input.MergeAttribute("type", type);
            input.MergeAttribute("value", value);

            if (isChecked)
            {
                input.MergeAttribute("checked", "checked");
            }

            sb.AppendLine(input.ToString());
            sb.AppendLine(label.ToString());

            return sb.ToString();
        }

        private static string GenerateOptionHtml(string text, string value, bool isSelected)
        {
            StringBuilder sb = new StringBuilder();
            TagBuilder option = new TagBuilder("option");
            option.SetInnerText(text);
            option.MergeAttribute("value", value);
            if (isSelected)
            {
                option.MergeAttribute("selected", "selected");
            }
            sb.AppendLine(option.ToString());

            return sb.ToString();
        }
    }
}
